#include <stdio.h>

#define TRACE printf

class RefCount {
private:
	int crefs;

public:
	RefCount(void){
		crefs = 0;
	}

	~RefCount(){
		TRACE("goodbye(%d)\n", crefs);
	}
	
	void upcount(void){
		++crefs;
		TRACE("up to %d\n",crefs);
	}
	
	void downcount(void){
		if(--crefs == 0)
			delete this;
		else
			TRACE("downto %d\n",crefs);
	}
	
};

class Sample : public RefCount{
public:
	void doSomething(void){
		TRACE("Did something\n");
	}
};


template <class T> class Ptr {
	T* p;
public:
	Ptr(T* p_) : p(p_){
		TRACE("constructor\n");
		p->upcount();
	}

	~Ptr(void){
		TRACE("deconstructor");
		p->downcount();
	}

	operator T*(void){
		TRACE("cast");
		return p;
	}
	
	T& operator*(void)
	{
		TRACE("operand*\n");
		return *p;
	}
	
	T* operator->(void){
		TRACE("operand->\n");
		return p;
	}

	Ptr& operator=(Ptr<T> &p_){
		return operator=((T*)p_);
	}

	Ptr& operator=(T* p_)
	{
		p_->upcount();
		p->downcount();
		p=p_;
		return *this;
	}

	Ptr(const Ptr<T> &p_){
		p = p_.p;
		p->upcount();
	}
};

int main(int argc, char *argv[])
{
	Ptr<Sample> p = new Sample;
	Ptr<Sample> p2 = new Sample;
	
	p = p2; // 
	p->doSomething();
	
	return 0;
}
